import { SignalMessage } from "../type";
import {
  PeerConnectionManager,
  IceServerConfig,
} from "./peer-connection-manager";
import { MediaStreamManager } from "./media-stream-manager";
import { SignalClient } from "./signal-client";
import { SignalHandler } from "./signal-handler";

export class WebRTCClient {
  private clientId: string;
  private roomId: string;
  private signalClient: SignalClient;
  private mediaStreamManager: MediaStreamManager;
  private signalHandler: SignalHandler;
  private peerConnectionManager: PeerConnectionManager;

  public onLocalStreamReady: (stream: MediaStream) => void;
  public onRemoteStreamReady: (stream: MediaStream) => void;

  constructor(
    url: string,
    iceServerConfig: IceServerConfig = {
      iceServers: [
        { urls: 'stun:stun.l.google.com:19302' },
        { urls: 'stun:stun1.l.google.com:19302' },
    ]
    }
  ) {
    this.mediaStreamManager = new MediaStreamManager();
    this.signalClient = new SignalClient(url);
    this.peerConnectionManager = new PeerConnectionManager(
      iceServerConfig,
      this.mediaStreamManager,
      (candidate) => {
        this.handleCandiadte(candidate);
      },
      (track) => {
        this.onRemoteStreamReady(track);
      }
    );
    this.signalHandler = new SignalHandler(
      this.signalClient,
      this.peerConnectionManager,
      (clientId, roomId) => {
        this.clientId = clientId;
        this.roomId = roomId;
      }
    );
    this.signalClient.onMessage((msg) => this.signalHandler.handleMessage(msg));
  }

  private handleCandiadte(candidate: RTCIceCandidate) {
    this.signalClient.send({
      type: "candidate",
      from: this.clientId,
      payload: candidate,
      roomId: this.roomId,
    } as SignalMessage);
  }

  public async start(roomId?: string) {
    await this.signalClient.connect();

    await this.mediaStreamManager.getLocalStream().then((stream) => {
      this.onLocalStreamReady?.(stream);
    }).catch((err)=>{
      console.error("getLocalStream error",err)
      throw err
    })

    const joinMessage: SignalMessage = {
      type: "join",
      ...(roomId && { roomId })
    };
    console.log("joinMessage",joinMessage)

    this.signalClient.send(joinMessage);
  }

  public stop(): void {
    this.signalClient.disconnect();
    this.peerConnectionManager.close();
    this.mediaStreamManager.stopLocalStream();
  }
}
